﻿using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;

namespace Ant.ICommon.Utilities
{
    public class Cast
    {
        #region "Type Convert"

        /// <summary>
        /// 类型转换。
        /// </summary>
        /// <typeparam name="T">要转成的类型。</typeparam>
        /// <param name="obj">转换值。</param>
        /// <param name="def">默认值。</param>
        /// <returns>转换后的值。</returns>
        public static T To<T>(object obj, T def = default(T))
        {
            T result;
            if (obj == null)
                result = def;
            else
            {
                try
                {
                    try
                    {
                        result = (T)obj;
                    }
                    catch
                    {
                        result = (T)Convert.ChangeType(obj, typeof(T));
                    }
                }
                catch
                {
                    result = def;
                }
            }
            return result == null ? def : result;
        }

        /// <summary>
        /// 类型转换。
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <param name="typeFullName">转换的类型的完全限定名。</param>
        /// <returns></returns>
        public static T ToByTypeName<T>(object obj, string typeFullName)
        {
            return (T)ToObject(obj, typeFullName);
        }

        /// <summary>
        /// 将对象转换成指定类型。
        /// </summary>
        /// <param name="obj">对象。</param>
        /// <param name="typeFullName">类型的完全限定名。</param>
        /// <param name="def">转换失败时的默认值。</param>
        /// <returns>转换后的值。</returns>
        public static object ToObject(object obj, string typeFullName, object def = null)
        {
            if (string.IsNullOrWhiteSpace(typeFullName)) return null;
            Type type = Type.GetType(typeFullName);
            return ToObject(obj, type, def);
        }

        /// <summary>
        /// 将对象转换成指定类型。
        /// </summary>
        /// <param name="obj">对象。</param>
        /// <param name="type">转换的目标类型。</param>
        /// <param name="def">转换失败时的默认值。</param>
        /// <returns>转换后的值。</returns>
        public static object ToObject(object obj, Type type, object def = null)
        {
            if (type == null) return null;
            try
            {
                return Convert.ChangeType(obj, type);
            }
            catch
            {
                return def;
            }
        }

        /// <summary>
        /// 将对象转换成Int。
        /// </summary>
        /// <param name="obj">对象。</param>
        /// <param name="def">转换失败的默认值。</param>
        /// <returns>Int。</returns>
        public static int ToInt(object obj, int def = 0)
        {
            int result = 0;
            if (obj != null)
                if (int.TryParse(obj.ToString(), out result))
                    return result;
            return def;
        }

        /// <summary>
        /// 将对象转换成可空的Int值。
        /// </summary>
        /// <param name="obj">对象。</param>
        /// <param name="def">转换失败时的默认值。</param>
        /// <returns>可空的Int值。</returns>
        public static int? ToInt(object obj, int? def = null)
        {
            int result = 0;
            if (obj != null)
                if (int.TryParse(obj.ToString(), out result))
                    return result;
            return def;
        }

        /// <summary>
        /// 将对象转换成字符串。
        /// </summary>
        /// <param name="obj">对象。</param>
        /// <param name="def">转换失败时的默认值。</param>
        /// <param name="format">格式（可空）。</param>
        /// <returns>字符串。</returns>
        public static string ToString(object obj, string def = null, string format = null)
        {
            if (obj == null)
                return def;
            string result = obj.ToString();
            if (string.IsNullOrWhiteSpace(format))
                return result;
            else
            {
                try
                {
                    return string.Format(format, result);
                }
                catch
                {
                    return result;
                }
            }
        }

        /// <summary>
        /// 将对象转换成Double。
        /// </summary>
        /// <param name="obj">对象。</param>
        /// <param name="def">转换失败时的默认值。</param>
        /// <returns>Double。</returns>
        public static double ToDouble(object obj, double def = 0)
        {
            double result = 0;
            if (obj != null)
                if (double.TryParse(obj.ToString(), out result))
                    return result;
            return def;
        }

        /// <summary>
        /// 将对象转换成Decimal。
        /// </summary>
        /// <param name="obj">对象。</param>
        /// <param name="def">转换失败时的默认值。</param>
        /// <returns>Decimal。</returns>
        public static decimal ToDecimal(object obj, decimal def = 0)
        {
            decimal result = 0;
            if (obj != null)
                if (decimal.TryParse(obj.ToString(), out result))
                    return result;
            return def;
        }

        /// <summary>
        /// 将对象转换成Long。
        /// </summary>
        /// <param name="obj">对象。</param>
        /// <param name="def">转换失败时的默认值。</param>
        /// <returns>Long。</returns>
        public static long ToLong(object obj, long def = 0)
        {
            long result = 0;
            if (obj != null)
                if (long.TryParse(obj.ToString(), out result))
                    return result;
            return def;
        }

        /// <summary>
        /// 将对象转换成可空的Long。
        /// </summary>
        /// <param name="obj">对象。</param>
        /// <param name="def">转换失败时的默认值。</param>
        /// <returns>Long。</returns>
        public static long? ToLong(object obj, long? def = null)
        {
            long result = 0;
            if (obj != null)
                if (long.TryParse(obj.ToString(), out result))
                    return result;
            return def;
        }

        /// <summary>
        /// 将对象转换成DateTime。
        /// </summary>
        /// <param name="obj">对象。</param>
        /// <param name="def">转换失败时的默认值。</param>
        /// <returns>DateTime。</returns>
        public static DateTime ToDateTime(object obj, DateTime def = default(DateTime))
        {
            DateTime result;
            if (obj != null)
                if (DateTime.TryParse(obj.ToString(), out result))
                    return result;
            return def;
        }

        /// <summary>
        /// 将对象转换成可空的DateTime。
        /// </summary>
        /// <param name="obj">对象。</param>
        /// <param name="def">转换失败时的默认值。</param>
        /// <returns>可空的DateTime。</returns>
        public static DateTime? ToDateTime(object obj, DateTime? def = null)
        {
            DateTime result;
            if (obj != null)
            {
                Regex regex = new Regex("\\d{8}$");
                Match m = regex.Match(obj.ToString());
                if (m.Success)
                {
                    obj = m.Value.Substring(0, 4) + "-" + m.Value.Substring(4, 2) + "-" + m.Value.Substring(6, 2);
                }
                if (DateTime.TryParse(obj.ToString(), out result))
                {
                    return result;
                }
            }
            return def;
        }

        /// <summary>
        /// 将对象转换成Boolean。
        /// </summary>
        /// <param name="obj">对象。</param>
        /// <param name="def">转换失败时的默认值。</param>
        /// <returns>Boolean。</returns>
        public static bool ToBoolean(object obj, bool def = false)
        {
            if (obj == null) return def;
            if (obj is string)
                return obj.ToString().Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase);
            else if (obj is int)
                return int.Parse(obj.ToString()) > 0;
            return Convert.ToBoolean(obj);
        }

        /// <summary>
        /// 将对象转换成Single。
        /// </summary>
        /// <param name="obj">对象。</param>
        /// <param name="def">转换失败时的默认值。</param>
        /// <returns>Single。</returns>
        public static float ToSingle(object obj, float def = 0)
        {
            float result = 0;
            if (obj != null)
                if (float.TryParse(obj.ToString(), out result))
                    return result;
            return def;
        }

        /// <summary>
        /// 将对象转换成Char。
        /// </summary>
        /// <param name="obj">对象。</param>
        /// <param name="def">转换失败时的默认值。</param>
        /// <returns>Char。</returns>
        public static char ToChar(object obj, char def = default(char))
        {
            char result;
            if (obj != null)
                if (char.TryParse(obj.ToString(), out result))
                    return result;
            return def;
        }

        /// <summary>
        /// 转换List内的元素。
        /// </summary>
        /// <typeparam name="TResult">结果类型。</typeparam>
        /// <param name="sources">源集合。</param>
        /// <returns>转换后的集合。</returns>
        public static List<TResult> ToList<TResult>(dynamic sources) where TResult : class
        {
            List<TResult> results = new List<TResult>();
            if (Is.Empty(sources)) return results;
            TResult result = null;
            foreach (var item in sources)
            {
                result = (TResult)item;
                if (result != null)
                    results.Add(result);
            }
            return results;
        }

        #endregion "Type Convert"

        #region "GetInstance"

        /// <summary>
        /// 创建泛型实例。
        /// </summary>
        /// <typeparam name="T">实例类型。</typeparam>
        /// <param name="typeFullName">类的完全限定名。</param>
        /// <returns>泛型实例。</returns>
        public static T GetInstance<T>(string typeFullName)
        {
            object instance = GetInstance(typeFullName);
            T result = Cast.To<T>(instance);
            if (instance != null && result == null)
                throw new Exception(string.Format("{0} 转换成 {1} 失败。", typeFullName, typeof(T).FullName));
            return result;
        }

        /// <summary>
        /// 创建实例。
        /// </summary>
        /// <param name="typeFullName">类的完全限定名。</param>
        /// <returns>实例。</returns>
        public static object GetInstance(string typeFullName)
        {
            Type type = null;
            try
            {
                type = Type.GetType(typeFullName);
            }
            catch
            {
                throw new ArgumentNullException("创建实例失败，实例的完全限定名：" + typeFullName);
            }

            if (typeFullName == null)
                throw new ArgumentException("找不到类型：" + typeFullName, "typeFullName");

            return Activator.CreateInstance(type);
        }

        /// <summary>
        /// 创建实例。
        /// </summary>
        /// <param name="type">类型。</param>
        /// <returns>实例。</returns>
        public static object GetInstance(Type type)
        {
            return Activator.CreateInstance(type);
        }

        #endregion "GetInstance"
    }
}